﻿using System;

using System.IO;
using System.Drawing.Imaging;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace MSL.Utility.Images
{
    /// <summary>
    /// 图像操作类（用于图片格式的转换、图片缩放、生成缩略图）
    /// ChangeImageSize（）、MakeThumbnail（）
    /// </summary>
    public class ImageHelper
    {
        #region 格式转换
        /// <summary>
        /// 图片格式转换
        /// </summary>
        /// <param name="oriPath">原始文件绝对路径</param>
        /// <param name="desiredPath">生成目标文件绝对路径</param>
        /// <returns></returns>
        ///  JPG是有损压缩 有可能会降低图像清晰度，而像素不会降低  
        ///  GIF是无损压缩 不会降低原图图像清晰度和像素的，但是GIF格式只支持256色图像。
        public static bool ConvertImage(string oriPath, string desiredPath)
        {
            string extname = desiredPath.Substring(desiredPath.LastIndexOf('.') + 1).ToLower();
            ImageFormat DesiredFormat;

            switch (extname)
            {
                case "bmp": DesiredFormat = ImageFormat.Bmp; break;
                case "gif": DesiredFormat = ImageFormat.Gif; break;
                case "jpeg": DesiredFormat = ImageFormat.Jpeg; break;
                case "ico": DesiredFormat = ImageFormat.Icon; break;
                case "png": DesiredFormat = ImageFormat.Png; break;
                default: DesiredFormat = ImageFormat.Jpeg; break;
            }
            try
            {
                System.Drawing.Image imgFile = System.Drawing.Image.FromFile(oriPath);
                imgFile.Save(desiredPath, DesiredFormat);
                return true;
            }
            catch (Exception)
            {
                throw new Exception();
            }
        }
        #endregion

        #region 图片缩放
        /// <summary>
        /// 图片固定大小缩放
        /// </summary>
        /// <param name="oriPath">源文件绝对地址</param>
        /// <param name="desiredPath">目标文件绝对地址</param>
        /// <param name="width">目标文件宽</param>
        /// <param name="height">目标文件高</param>
        /// <param name="imageFormat">图片文件格式</param>
        public static bool ImageZoom(string oriPath, string desiredPath, int width, int height, ImageFormat imageFormat)
        {
            bool result = false;
            try
            {
                using (Image sourceImage = System.Drawing.Image.FromFile(oriPath))//来源图片定义
                {
                    using (Bitmap bit = ImageZoom(sourceImage, width, height))
                    {
                        bit.Save(desiredPath, imageFormat);
                        if (File.Exists(desiredPath))//如果文件存在则成功
                        {
                            result = true;
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw new Exception();
                //return false;
            }
            return result;
        }
        /// <summary> 
        /// 按照比例缩小图片 
        /// </summary> 
        /// <param name="srcImage">要缩小的图片</param> 
        /// <param name="percent">缩小比例</param> 
        /// <returns>缩小后的结果</returns> 
        public static Bitmap ImageZoom(Image srcImage, double percent)
        {
            int newH = int.Parse(Math.Round(srcImage.Height * percent).ToString());
            int newW = int.Parse(Math.Round(srcImage.Width * percent).ToString());
            return ImageZoom(srcImage, newW, newH);
        }
        /// <summary> 
        /// 按照指定大小缩放图片 
        /// </summary> 
        /// <param name="srcImage"></param> 
        /// <param name="iWidth"></param> 
        /// <param name="iHeight"></param> 
        /// <returns></returns> 
        public static Bitmap ImageZoom(Image srcImage, int iWidth, int iHeight)
        {
            try
            {
                using (Bitmap b = new Bitmap(iWidth, iHeight))
                {
                    Graphics g = Graphics.FromImage(b);// 插值算法的质量 
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    g.DrawImage(srcImage, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(0, 0, srcImage.Width, srcImage.Height), GraphicsUnit.Pixel);
                    return b;
                }
            }
            catch (Exception)
            {
                throw new Exception();
                //return false;
            }
        }
        #endregion

        #region 压缩
        /// <summary> 
        /// jpeg图片压缩 
        /// </summary> 
        /// <param name="oriPath">源文件路径</param> 
        /// <param name="outPath">输出文件路径</param> 
        /// <returns></returns> 
        public static bool Compress(string oriPath, string outPath)
        {
            return Compress(oriPath, outPath, 100);
        }
        /// <summary> 
        /// JPEG图片压缩 
        /// </summary> 
        /// <param name="oriPath">源文件路径</param> 
        /// <param name="outPath">输出文件路径</param> 
        /// <param name="compressionRatio">设置压缩的比例1-100</param> 
        /// <returns></returns> 
        public static bool Compress(string oriPath, string outPath, int compressionRatio)
        {
            //设置压缩质量 
            EncoderParameters ep = new EncoderParameters();
            long[] quality = new long[1];
            quality[0] = compressionRatio;
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            ep.Param[0] = eParam;
            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo jpegICIinfo = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                using (System.Drawing.Image originalImage = System.Drawing.Image.FromFile(oriPath))
                {
                    ImageFormat tFormat = originalImage.RawFormat;
                    if (jpegICIinfo != null)
                    {
                        originalImage.Save(outPath, jpegICIinfo, ep);//dFile是压缩后的新路径 
                    }
                    else
                    {
                        originalImage.Save(outPath, tFormat);
                    }
                    return true;
                }
            }
            catch (Exception)
            {
                throw new Exception();
                //return false;
            }
        }
        #endregion

        #region 剪裁

        /// <summary> 
        /// 剪裁 -- 用GDI+
        /// </summary> 
        /// <param name="b">原始Bitmap</param> 
        /// <param name="startX">开始坐标X</param> 
        /// <param name="startY">开始坐标Y</param> 
        /// <param name="iWidth">宽度</param> 
        /// <param name="iHeight">高度</param> 
        /// <returns>剪裁后的Bitmap</returns> 
        public static Bitmap CutImage(Image b, int startX, int startY, int iWidth, int iHeight)
        {
            if (b == null)
            {
                return null;
            }
            int w = b.Width;
            int h = b.Height;
            if (startX >= w || startY >= h)
            {
                // 开始截取坐标过大时，结束处理 
                return null;
            }
            if (startX + iWidth > w)
            {
                // 宽度过大时只截取到最大大小 
                iWidth = w - startX;
            }
            if (startY + iHeight > h)
            {
                // 高度过大时只截取到最大大小 
                iHeight = h - startY;
            }
            try
            {
                Bitmap bmpOut = new Bitmap(iWidth, iHeight);
                Graphics g = Graphics.FromImage(bmpOut);
                g.DrawImage(b, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(startX, startY, iWidth, iHeight), GraphicsUnit.Pixel);
                g.Dispose();
                return bmpOut;
            }
            catch (Exception)
            {
                throw new Exception();
                //return false;
            }
        }
        #endregion

        #region 生成缩略图
        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImage">原图</param>
        /// <param name="thumbnailPath">缩略图路径（物理路径）</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的方式</param>    
        /// <param name="picExtension">图片后缀[不加点]</param>
        public static bool MakeThumbnail(Image originalImage, string thumbnailPath, int width, int height, Zoom mode, string picExtension)
        {
            bool result = false;
            if (originalImage == null) return result;

            int towidth = width;
            int toheight = height;

            int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;
            string path = thumbnailPath.Remove(thumbnailPath.LastIndexOf("\\"));
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            switch (mode)
            {
                case Zoom.HW://指定高宽缩放（可能变形）                
                    break;
                case Zoom.W://指定宽，高按比例                    
                    toheight = originalImage.Height * width / originalImage.Width;
                    break;
                case Zoom.H://指定高，宽按比例
                    towidth = originalImage.Width * height / originalImage.Height;
                    break;
                case Zoom.Cut://指定高宽裁减（不变形）                
                    if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height * towidth / toheight;
                        y = 0;
                        x = (originalImage.Width - ow) / 2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                default:
                    break;
            }
            System.Drawing.Image bitmap = new System.Drawing.Bitmap(towidth, toheight);
            //新建画板
            System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap);
            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
            //设置高质量，低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //清空画布并以透明背景色填充
            g.Clear(System.Drawing.Color.Transparent);
            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new System.Drawing.Rectangle(0, 0, towidth, toheight),
                new System.Drawing.Rectangle(x, y, ow, oh),
                System.Drawing.GraphicsUnit.Pixel);

            try
            {
                if (!picExtension.StartsWith(".")) picExtension = "." + picExtension;

                switch (picExtension.ToLower())
                {
                    case ".jpg":
                    case ".jpeg":
                    case ".pjpeg":
                        bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Jpeg);
                        break;
                    case ".gif":
                        bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Gif);
                        break;
                    case ".bmp":
                        bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Bmp);
                        break;
                    case ".png":
                        bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Png);
                        break;
                    default:
                        bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Jpeg);
                        break;
                }
                result = true;
            }
            catch (System.Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
            return result;
        }

        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="picStream">原图流</param>
        /// <param name="thumbnailPath">缩略图路径（物理路径）</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的方式</param>    
        /// <param name="picExtension">图片后缀[不加点]</param>
        public static bool MakeThumbnail(Stream picStream, string thumbnailPath, int width, int height, Zoom mode, string picExtension)
        {
            System.Drawing.Image originalImage = System.Drawing.Image.FromStream(picStream);
            return MakeThumbnail(originalImage, thumbnailPath, width, height, mode, picExtension);
        }

        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径（物理路径）</param>
        /// <param name="thumbnailPath">缩略图路径（物理路径）</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的方式</param>    
        public static bool MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, Zoom mode)
        {
            bool result = false;
            using (System.Drawing.Image originalImage = System.Drawing.Image.FromFile(originalImagePath))
            {
                FileInfo f = new FileInfo(originalImagePath);
                result = MakeThumbnail(originalImage, thumbnailPath, width, height, mode, f.Extension);
            }
            return result;
        }

        #endregion

        #region 调整光暗
        /// <summary>
        /// 调整光暗
        /// </summary>
        /// <param name="mybm">原始图片</param>
        /// <param name="width">原始图片的长度</param>
        /// <param name="height">原始图片的高度</param>
        /// <param name="val">增加或减少的光暗值</param>
        public Bitmap LDPic(Bitmap mybm, int width, int height, int val)
        {
            Bitmap bm = new Bitmap(width, height);//初始化一个记录经过处理后的图片对象
            int x, y, resultR, resultG, resultB;//x、y是循环次数，后面三个是记录红绿蓝三个值的
            Color pixel;
            for (x = 0; x < width; x++)
            {
                for (y = 0; y < height; y++)
                {
                    pixel = mybm.GetPixel(x, y);//获取当前像素的值
                    resultR = pixel.R + val;//检查红色值会不会超出[0, 255]
                    resultG = pixel.G + val;//检查绿色值会不会超出[0, 255]
                    resultB = pixel.B + val;//检查蓝色值会不会超出[0, 255]
                    bm.SetPixel(x, y, Color.FromArgb(resultR, resultG, resultB));//绘图
                }
            }
            return bm;
        }
        #endregion

        #region 反色处理
        /// <summary>
        /// 反色处理
        /// </summary>
        /// <param name="mybm">原始图片</param>
        /// <param name="width">原始图片的长度</param>
        /// <param name="height">原始图片的高度</param>
        public Bitmap RePic(Bitmap mybm, int width, int height)
        {
            Bitmap bm = new Bitmap(width, height);//初始化一个记录处理后的图片的对象
            int x, y, resultR, resultG, resultB;
            Color pixel;
            for (x = 0; x < width; x++)
            {
                for (y = 0; y < height; y++)
                {
                    pixel = mybm.GetPixel(x, y);//获取当前坐标的像素值
                    resultR = 255 - pixel.R;//反红
                    resultG = 255 - pixel.G;//反绿
                    resultB = 255 - pixel.B;//反蓝
                    bm.SetPixel(x, y, Color.FromArgb(resultR, resultG, resultB));//绘图
                }
            }
            return bm;
        }
        #endregion

        #region 浮雕处理
        /// <summary>
        /// 浮雕处理
        /// </summary>
        /// <param name="oldBitmap">原始图片</param>
        /// <param name="Width">原始图片的长度</param>
        /// <param name="Height">原始图片的高度</param>
        public Bitmap FD(Bitmap oldBitmap, int Width, int Height)
        {
            Bitmap newBitmap = new Bitmap(Width, Height);
            Color color1, color2;
            for (int x = 0; x < Width - 1; x++)
            {
                for (int y = 0; y < Height - 1; y++)
                {
                    int r = 0, g = 0, b = 0;
                    color1 = oldBitmap.GetPixel(x, y);
                    color2 = oldBitmap.GetPixel(x + 1, y + 1);
                    r = Math.Abs(color1.R - color2.R + 128);
                    g = Math.Abs(color1.G - color2.G + 128);
                    b = Math.Abs(color1.B - color2.B + 128);
                    if (r > 255) r = 255;
                    if (r < 0) r = 0;
                    if (g > 255) g = 255;
                    if (g < 0) g = 0;
                    if (b > 255) b = 255;
                    if (b < 0) b = 0;
                    newBitmap.SetPixel(x, y, Color.FromArgb(r, g, b));
                }
            }
            return newBitmap;
        }
        #endregion

        #region 拉伸图片
        /// <summary>
        /// 拉伸图片
        /// </summary>
        /// <param name="bmp">原始图片</param>
        /// <param name="newW">新的宽度</param>
        /// <param name="newH">新的高度</param>
        public static Bitmap ResizeImage(Bitmap bmp, int newW, int newH)
        {
            try
            {
                Bitmap bap = new Bitmap(newW, newH);
                Graphics g = Graphics.FromImage(bap);
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.DrawImage(bap, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bap.Width, bap.Height), GraphicsUnit.Pixel);
                g.Dispose();
                return bap;
            }
            catch
            {
                return null;
            }
        }
        #endregion

        #region 滤色处理
        /// <summary>
        /// 滤色处理
        /// </summary>
        /// <param name="mybm">原始图片</param>
        /// <param name="width">原始图片的长度</param>
        /// <param name="height">原始图片的高度</param>
        public Bitmap FilPic(Bitmap mybm, int width, int height)
        {
            Bitmap bm = new Bitmap(width, height);//初始化一个记录滤色效果的图片对象
            int x, y;
            Color pixel;

            for (x = 0; x < width; x++)
            {
                for (y = 0; y < height; y++)
                {
                    pixel = mybm.GetPixel(x, y);//获取当前坐标的像素值
                    bm.SetPixel(x, y, Color.FromArgb(0, pixel.G, pixel.B));//绘图
                }
            }
            return bm;
        }
        #endregion

        #region 左右翻转
        /// <summary>
        /// 左右翻转
        /// </summary>
        /// <param name="mybm">原始图片</param>
        /// <param name="width">原始图片的长度</param>
        /// <param name="height">原始图片的高度</param>
        public Bitmap RevPicLR(Bitmap mybm, int width, int height)
        {
            Bitmap bm = new Bitmap(width, height);
            int x, y, z; //x,y是循环次数,z是用来记录像素点的x坐标的变化的
            Color pixel;
            for (y = height - 1; y >= 0; y--)
            {
                for (x = width - 1, z = 0; x >= 0; x--)
                {
                    pixel = mybm.GetPixel(x, y);//获取当前像素的值
                    bm.SetPixel(z++, y, Color.FromArgb(pixel.R, pixel.G, pixel.B));//绘图
                }
            }
            return bm;
        }
        #endregion

        #region 上下翻转
        /// <summary>
        /// 上下翻转
        /// </summary>
        /// <param name="mybm">原始图片</param>
        /// <param name="width">原始图片的长度</param>
        /// <param name="height">原始图片的高度</param>
        public Bitmap RevPicUD(Bitmap mybm, int width, int height)
        {
            Bitmap bm = new Bitmap(width, height);
            int x, y, z;
            Color pixel;
            for (x = 0; x < width; x++)
            {
                for (y = height - 1, z = 0; y >= 0; y--)
                {
                    pixel = mybm.GetPixel(x, y);//获取当前像素的值
                    bm.SetPixel(x, z++, Color.FromArgb(pixel.R, pixel.G, pixel.B));//绘图
                }
            }
            return bm;
        }
        #endregion

        #region 图片灰度化
        public Color Gray(Color c)
        {
            int rgb = Convert.ToInt32((double)(((0.3 * c.R) + (0.59 * c.G)) + (0.11 * c.B)));
            return Color.FromArgb(rgb, rgb, rgb);
        }
        #endregion

        #region 转换为黑白图片
        /// <summary>
        /// 转换为黑白图片
        /// </summary>
        /// <param name="mybt">要进行处理的图片</param>
        /// <param name="width">图片的长度</param>
        /// <param name="height">图片的高度</param>
        public Bitmap BWPic(Bitmap mybm, int width, int height)
        {
            Bitmap bm = new Bitmap(width, height);
            int x, y, result; //x,y是循环次数，result是记录处理后的像素值
            Color pixel;
            for (x = 0; x < width; x++)
            {
                for (y = 0; y < height; y++)
                {
                    pixel = mybm.GetPixel(x, y);//获取当前坐标的像素值
                    result = (pixel.R + pixel.G + pixel.B) / 3;//取红绿蓝三色的平均值
                    bm.SetPixel(x, y, Color.FromArgb(result, result, result));
                }
            }
            return bm;
        }
        #endregion

        #region 获取图片中的各帧
        /// <summary>
        /// 获取图片中的各帧
        /// </summary>
        /// <param name="pPath">图片路径</param>
        /// <param name="pSavePath">保存路径</param>
        public void GetFrames(string pPath, string pSavedPath)
        {
            using (Image gif = Image.FromFile(pPath))
            {
                FrameDimension fd = new FrameDimension(gif.FrameDimensionsList[0]);
                int count = gif.GetFrameCount(fd); //获取帧数(gif图片可能包含多帧，其它格式图片一般仅一帧)
                for (int i = 0; i < count; i++)    //以Jpeg格式保存各帧
                {
                    gif.SelectActiveFrame(fd, i);
                    gif.Save(pSavedPath + "\\frame_" + i + ".jpg", ImageFormat.Jpeg);
                }
            }
        }
        #endregion
    }
}
